package jp.co.tms.internal.runserver.util;

import jp.co.tms.internal.runserver.protocol.FinishPackage;
import jp.co.tms.internal.runserver.protocol.HandshakeAckPackage;
import jp.co.tms.internal.runserver.protocol.IPackage;
import jp.co.tms.internal.runserver.protocol.RunAckPackage;
import jp.co.tms.internal.util.NumberUtil;

public class PackageUtil {

	
	public static IPackage getPackage( byte[] buffer ){
		
		if ( buffer.length != IPackage.PACKAGE_LEN ){
			return null;
		}
		
		if ( buffer[0] != 0x00 
				|| ( buffer[buffer.length - 1] & 0xFF ) != 0xFF ){
			return null;	
		}
		
		int type = getIntFromByteArray( buffer, IPackage.SYS_BYTE_SIZE );
		int length = getIntFromByteArray( buffer,
				IPackage.SYS_BYTE_SIZE + IPackage.SYS_INT_SIZE
				);
		
		byte[] command = null;
		if ( length != 0 && length <= IPackage.PACKAGE_DATA_LEN ){
			command = new byte[length];
			System.arraycopy( buffer,
					IPackage.SYS_BYTE_SIZE + 2 * IPackage.SYS_INT_SIZE, 
					command, 
					0, 
					length
					) ;
		}
		
		IPackage packagePtr = null;
		switch ( type ) {
		case IPackage.PT_HANDSHAKE_ACK :
			packagePtr = getHankShakeAckPackage( command ); 
			break;
		case IPackage.PT_RUN_ACK :
			packagePtr = getRunAckPackage( command );
			break;
		case IPackage.PT_KILL_ACK :
			packagePtr = getKillAckPackage( command );
			break;
		case IPackage.PT_FINISH :
			packagePtr = getFinishPackage( command );
			break;
		default:;
		}
		
		return packagePtr;
	}
	
	private static IPackage getHankShakeAckPackage(byte[] data){
		
		if ( data == null 
				|| data.length != IPackage.SYS_INT_SIZE * 2 ){
			return null;
		}

		int serverId = getIntFromByteArray( data, 0 );
		int cpus = getIntFromByteArray( data, IPackage.SYS_INT_SIZE );
		
		return new HandshakeAckPackage(serverId, cpus);
	}
	
	private static IPackage getRunAckPackage(byte[] data){
		
		if ( data == null 
				|| data.length != IPackage.SYS_INT_SIZE ){
			return null;
		}
		
		return new RunAckPackage( getIntFromByteArray( data, 0) );
	}
	
	private static IPackage getKillAckPackage(byte[] data){
		if ( data == null 
				|| data.length != IPackage.SYS_INT_SIZE ){
			return null;
		}
	
		return new RunAckPackage( getIntFromByteArray( data, 0 ) );	
	}
	
	private static IPackage getFinishPackage(byte[] data){
		if ( data == null 
				|| data.length != IPackage.SYS_INT_SIZE ){
			return null;
		}
		
		return new FinishPackage(getIntFromByteArray(data, 0));
	}
	
	private static int getIntFromByteArray(byte[] data, int startPos){
		byte[] buffer = new byte[IPackage.SYS_INT_SIZE];
		System.arraycopy(data,
				startPos,
				buffer,
				0, 
				IPackage.SYS_INT_SIZE
				);
		return NumberUtil.byteArrayToInt( buffer );		
	}
}
